package me.kagami.myplugin.topic;


import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.FileColorManager;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * File Editor Listener implementation for tab highlight
 * Created by Tomasz Obszarny on 19.01.2017.
 */
public class TabHighlighterFileEditorListener implements FileEditorManagerListener {

    private static final Logger LOGGER = Logger.getInstance(TabHighlighterFileEditorListener.class);
    private final Project myProject;
    private LinkedList<VirtualFile> queue = new LinkedList<>();

    public TabHighlighterFileEditorListener(Project project) {
        this.myProject = project;
        initialize();
    }

    private void initialize() {
        FileEditorManager fileEditorManager = FileEditorManager.getInstance(myProject);
        FileEditor selectedEditor = fileEditorManager.getSelectedEditor();
        if (selectedEditor != null) {
            VirtualFile file = selectedEditor.getFile();
            SwingUtilities.invokeLater(() -> {
                queue.offer(file);
                final FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
                for (EditorWindow editorWindow : manager.getWindows()) {
                    highlightSafe(file, editorWindow, 0);
                }
            });
        }
    }

    @Override
    public void fileOpened(@NotNull FileEditorManager fileEditorManager, @NotNull VirtualFile virtualFile) {
        LOGGER.info(String.format("fileOpen %s", virtualFile.getUrl()));
    }

    @Override
    public void fileClosed(@NotNull FileEditorManager fileEditorManager, @NotNull VirtualFile virtualFile) {
    }

    @Override
    public void selectionChanged(@NotNull FileEditorManagerEvent fileEditorManagerEvent) {
        if (fileEditorManagerEvent.getManager().getProject().equals(myProject)) {
            final FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
            final FileColorManager fileColorManager = FileColorManager.getInstance(myProject);
            if (queue.contains(fileEditorManagerEvent.getNewFile())) {
                Iterator<VirtualFile> iterator = queue.iterator();
                while (iterator.hasNext()) {
                    VirtualFile next = iterator.next();
                    if (next.equals(fileEditorManagerEvent.getNewFile())) {
                        iterator.remove();
                    }
                }

            }
            if (queue.size() + 1 > 4) {
                VirtualFile virtualFile = queue.poll();
                for (EditorWindow editorWindow : manager.getWindows()) {
                    unhighlightSafe(fileColorManager, virtualFile, editorWindow);
                }
            }

            queue.offer(fileEditorManagerEvent.getNewFile());
            for (EditorWindow editorWindow : manager.getWindows()) {
                for (int i = 0; i < queue.size(); i++) {
                    VirtualFile virtualFile = queue.get(i);
                    highlightSafe(virtualFile, editorWindow, queue.size() - i - 1);
                }
            }
        }

    }


    private void highlightSafe(VirtualFile file, EditorWindow editorWindow, int i) {
        if (file != null && editorWindow.findFileComposite(file) != null) {
            highlight(file, editorWindow, i);
        }
    }

    private void unhighlightSafe(FileColorManager fileColorManager, VirtualFile oldFile, EditorWindow editorWindow) {
        if (oldFile != null && editorWindow.findFileComposite(oldFile) != null) {
            unhighlight(fileColorManager, oldFile, editorWindow);
        }
    }


    private void highlight(VirtualFile file, EditorWindow editorWindow, int i) {
        int rgb = 255 - i * 60;
        if (rgb < 0) {
            rgb = 0;
        }
        setTabColor(new Color(rgb, 0, 0), file, editorWindow);
    }

    private void unhighlight(@NotNull FileColorManager fileColorManager, VirtualFile file, EditorWindow editorWindow) {
        setTabColor(fileColorManager.getFileColor(file), file, editorWindow);
    }

    private void setTabColor(Color color, @NotNull VirtualFile file, @NotNull EditorWindow editorWindow) {
        final EditorWithProviderComposite fileComposite = editorWindow.findFileComposite(file);
        final int index = getEditorIndex(editorWindow, fileComposite);
        if (index >= 0) {
            if (editorWindow.getTabbedPane() != null) { //Distraction free mode // Presentation mode
                editorWindow.getTabbedPane().getTabs().getTabAt(index).setTabColor(color);
            }
        }
    }

    private int getEditorIndex(@NotNull EditorWindow editorWindow, EditorWithProviderComposite fileComposite) {
        return Arrays.asList(editorWindow.getEditors()).indexOf(fileComposite);
    }
}
